﻿using System;
using System.Text;
using System.Collections.Generic;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using VisualAgile.Controllers;
using System.Web.Mvc;
using System.Web.Security;
using System.Web.Routing;
using System.Security.Principal;
using System.Web;
using VisualAgile.DTO;
using VisualAgile.Web.Tests.Fakes;
using System.Collections;

namespace VisualAgile.Web.Tests
{
    /// <summary>
    /// Summary description for LoginController 
    /// </summary>
    [TestClass]
    public class LoginControllerTests : BaseControllerTests
    {
        public LoginControllerTests()
        {
            //
            // TODO: Add constructor logic here
            //
        }

        private TestContext testContextInstance;

        /// <summary>
        ///Gets or sets the test context which provides
        ///information about and functionality for the current test run.
        ///</summary>
        public TestContext TestContext
        {
            get
            {
                return testContextInstance;
            }
            set
            {
                testContextInstance = value;
            }
        }

        #region Additional test attributes
        //
        // You can use the following additional attributes as you write your tests:
        //
        // Use ClassInitialize to run code before running the first test in the class
        // [ClassInitialize()]
        // public static void MyClassInitialize(TestContext testContext) { }
        //
        // Use ClassCleanup to run code after all tests in a class have run
        // [ClassCleanup()]
        // public static void MyClassCleanup() { }
        //
        // Use TestInitialize to run code before running each test 
        // [TestInitialize()]
        // public void MyTestInitialize() { }
        //
        // Use TestCleanup to run code after each test has run
        // [TestCleanup()]
        // public void MyTestCleanup() { }
        //
        #endregion              

        [TestMethod]
        public void Authenticate_ShouldAuthenticateDefaultUserWithNoPassword()
        {
            // Arrange
            LoginController controller = GetLoginController();

            // Act
            var actionResult = (JsonResult)controller.Authenticate(new Guid("29DC7A46-52B5-4941-AAE2-F48592847E42"), null, null);

            // Results should be ResultDTO
            ResultDTO actionData = actionResult.Data as ResultDTO;
            Assert.IsNotNull(actionData, "No results found");

            // Result should be true            
            Assert.IsTrue(actionData.Result, actionData.Message);

            // there should be some users/stories/features
            //Assert.IsNotNull(actionData.Data, "User/Story/Feature data is null");

            // Assert
            //Assert.AreEqual("Home", result.RouteValues["controller"]);
            //Assert.AreEqual("Index", result.RouteValues["action"]);
        }

        [TestMethod]
        public void Authenticate_ShouldAuthenticateDefaultUserWithPassword()
        {
            // Arrange
            LoginController controller = GetLoginController();

            // Act
            var actionResult = (JsonResult)controller.Authenticate(new Guid("BE4B0656-8685-439e-B4EA-66D5C9BA7508"), new Guid("BE4B0656-8685-439e-B4EA-66D5C9BA7508"), "goodPass");

            // Results should be ResultDTO
            ResultDTO actionData = actionResult.Data as ResultDTO;
            Assert.IsNotNull(actionData, "No results found");

            // Result should be true            
            Assert.IsTrue(actionData.Result, actionData.Message);            
        }

        [TestMethod]
        public void Authenticate_ShouldAuthenticateUsers()
        {
            // Arrange
            LoginController controller = GetLoginController();

            // Act
            var actionResult = (JsonResult)controller.Authenticate(new Guid("2EBDBC36-3585-47b3-8709-BE3184956938"), new Guid("2EBDBC36-3585-47b3-8709-BE3184956938"), "goodPass");

            // Results should be ResultDTO
            ResultDTO actionData = actionResult.Data as ResultDTO;
            Assert.IsNotNull(actionData, "No results found");

            // Result should be true            
            Assert.IsTrue(actionData.Result, actionData.Message);
        }

        [TestMethod]
        public void LogOff()
        {
            // Arrange
            LoginController controller = GetLoginController();

            // Act
            RedirectToRouteResult result = (RedirectToRouteResult)controller.Logout();

            // Assert
            Assert.AreEqual("Home", result.RouteValues["controller"]);
            Assert.AreEqual("About", result.RouteValues["action"]);
        }

        private static LoginController GetLoginController()
        {
            VisualAgile.Controllers.LoginController.IFormsAuthentication formsAuth = new MockFormsAuthenticationService();
            MembershipProvider membershipProvider = new MockMembershipProvider();
            VisualAgile.Controllers.LoginController.AccountMembershipService membershipService = new VisualAgile.Controllers.LoginController.AccountMembershipService(membershipProvider);
            LoginController controller = new LoginController(formsAuth, membershipService);
            ControllerContext controllerContext = new ControllerContext(new MockHttpContext(), new RouteData(), controller);                   
            controller.ControllerContext = controllerContext;            
            return controller;
        }

        public class MockFormsAuthenticationService : VisualAgile.Controllers.LoginController.IFormsAuthentication
        {
            public void SignIn(string userName, bool createPersistentCookie)
            {
            }

            public void SignOut()
            {
            }
        }

        public class MockIdentity : IIdentity
        {
            public string AuthenticationType
            {
                get
                {
                    return "MockAuthentication";
                }
            }

            public bool IsAuthenticated
            {
                get
                {
                    return true;
                }
            }

            public string Name
            {
                get
                {
                    return "someUser";
                }
            }
        }

        public class MockPrincipal : IPrincipal
        {
            IIdentity _identity;

            public IIdentity Identity
            {
                get
                {
                    if (_identity == null)
                    {
                        _identity = new MockIdentity();
                    }
                    return _identity;
                }
            }

            public bool IsInRole(string role)
            {
                return false;
            }
        }

        public class MockMembershipUser : MembershipUser
        {
            public override bool ChangePassword(string oldPassword, string newPassword)
            {
                return newPassword.Equals("newPass");
            }
        }

        public class MockHttpContext : HttpContextBase
        {
            private IPrincipal _user;
            private IDictionary _items;

            public override IPrincipal User
            {
                get
                {
                    if (_user == null)
                    {
                        _user = new MockPrincipal();
                    }
                    return _user;
                }
                set
                {
                    _user = value;
                }
            }

            public override IDictionary Items 
            {
                get
                {
                    if (_items == null)
                    {                        
                        AllManagerFactory manager = new AllManagerFactory()
                        {
                            UserManager = new FakeUserManager(
                                    FakeUserData.CreateTestUsers()                                   
                                )
                        };

                        _items = new Dictionary<string, AllManagerFactory>();
                        _items.Add("ManagerFactory", manager);
                    }

                    return _items;
                }            
            }
        }

        public class MockMembershipProvider : MembershipProvider
        {
            string _applicationName;

            public override string ApplicationName
            {
                get
                {
                    return _applicationName;
                }
                set
                {
                    _applicationName = value;
                }
            }

            public override bool EnablePasswordReset
            {
                get
                {
                    return false;
                }
            }

            public override bool EnablePasswordRetrieval
            {
                get
                {
                    return false;
                }
            }

            public override int MaxInvalidPasswordAttempts
            {
                get
                {
                    return 0;
                }
            }

            public override int MinRequiredNonAlphanumericCharacters
            {
                get
                {
                    return 0;
                }
            }

            public override int MinRequiredPasswordLength
            {
                get
                {
                    return 6;
                }
            }

            public override string Name
            {
                get
                {
                    return null;
                }
            }

            public override int PasswordAttemptWindow
            {
                get
                {
                    return 3;
                }
            }

            public override MembershipPasswordFormat PasswordFormat
            {
                get
                {
                    return MembershipPasswordFormat.Clear;
                }
            }

            public override string PasswordStrengthRegularExpression
            {
                get
                {
                    return null;
                }
            }

            public override bool RequiresQuestionAndAnswer
            {
                get
                {
                    return false;
                }
            }

            public override bool RequiresUniqueEmail
            {
                get
                {
                    return false;
                }
            }

            public override bool ChangePassword(string username, string oldPassword, string newPassword)
            {
                throw new NotImplementedException();
            }

            public override bool ChangePasswordQuestionAndAnswer(string username, string password, string newPasswordQuestion, string newPasswordAnswer)
            {
                throw new NotImplementedException();
            }

            public override MembershipUser CreateUser(string username, string password, string email, string passwordQuestion, string passwordAnswer, bool isApproved, Object providerUserKey, out MembershipCreateStatus status)
            {
                MockMembershipUser user = new MockMembershipUser();

                if (username.Equals("someUser") && password.Equals("goodPass") && email.Equals("email"))
                {
                    status = MembershipCreateStatus.Success;
                }
                else
                {
                    // the 'email' parameter contains the status we want to return to the user
                    status = (MembershipCreateStatus)Enum.Parse(typeof(MembershipCreateStatus), email);
                }

                return user;
            }

            public override bool DeleteUser(string username, bool deleteAllRelatedData)
            {
                throw new NotImplementedException();
            }

            public override MembershipUserCollection FindUsersByEmail(string emailToMatch, int pageIndex, int pageSize, out int totalRecords)
            {
                throw new NotImplementedException();
            }

            public override MembershipUserCollection FindUsersByName(string usernameToMatch, int pageIndex, int pageSize, out int totalRecords)
            {
                throw new NotImplementedException();
            }

            public override MembershipUserCollection GetAllUsers(int pageIndex, int pageSize, out int totalRecords)
            {
                throw new NotImplementedException();
            }

            public override int GetNumberOfUsersOnline()
            {
                throw new NotImplementedException();
            }

            public override string GetPassword(string username, string answer)
            {
                throw new NotImplementedException();
            }

            public override string GetUserNameByEmail(string email)
            {
                throw new NotImplementedException();
            }

            public override MembershipUser GetUser(Object providerUserKey, bool userIsOnline)
            {
                throw new NotImplementedException();
            }

            public override MembershipUser GetUser(string username, bool userIsOnline)
            {
                return new MockMembershipUser();
            }

            public override string ResetPassword(string username, string answer)
            {
                throw new NotImplementedException();
            }

            public override bool UnlockUser(string userName)
            {
                throw new NotImplementedException();
            }

            public override void UpdateUser(MembershipUser user)
            {
                throw new NotImplementedException();
            }

            public override bool ValidateUser(string username, string password)
            {
                return password.Equals("goodPass");
            }

        }

    }
}
